/**
* Dashboard page - Award-winning feed-first design
* Facebook/Twitter-inspired infinite scroll experience
*/
'use client';
import { useQuery } from '@apollo/client';
import { useTranslations, useLocale } from 'next-intl';
import { useAuth } from '@/contexts/AuthContext';
import { Header } from '@/components/Header';
import { Footer } from '@/components/Footer';
import { ActivityFeed } from '@/components/dashboard/ActivityFeed';
import { ActiveDiscussionsCarousel } from '@/components/dashboard/ActiveDiscussionsCarousel';
import { GET_DASHBOARD_COUNTS, SEARCH_BILLS } from '@/lib/queries';
import { Link } from '@/i18n/navigation';
import { Users, FileText, Building, DollarSign, Search } from 'lucide-react';
import { format } from 'date-fns';
import { fr, enUS } from 'date-fns/locale';
// Current parliamentary session
const CURRENT_SESSION = '45-1';
/**
* Compact stat pill component
*/
function StatPill({
href,
value,
label,
icon: Icon,
}: {
href: string;
value: string | number;
label: string;
icon: React.ElementType;
}) {
return (
<Link
href={href as any}
className="flex-shrink-0 flex items-center gap-2 px-4 py-2 rounded-full bg-bg-elevated border border-border-subtle hover:border-accent-red hover:shadow-sm transition-all group"
>
<Icon size={16} className="text-accent-red" />
<span className="text-lg font-bold text-text-primary group-hover:text-accent-red transition-colors">
{value}
</span>
<span className="text-xs text-text-secondary">{label}</span>
</Link>
);
}
export default function DashboardPage() {
const t = useTranslations('dashboard');
const locale = useLocale();
const dateLocale = locale === 'fr' ? fr : enUS;
const { user } = useAuth();
// Get the user's first name
const firstName = user?.display_name?.split(' ')[0] || user?.full_name?.split(' ')[0];
// Format today's date
const today = new Date();
const formattedDate = format(today, 'EEEE, MMMM d', { locale: dateLocale });
// Fetch counts for stat pills
const { data: countsData } = useQuery(GET_DASHBOARD_COUNTS);
// Fetch bills for current session only (order paper = bills still in progress)
const { data: orderPaperData } = useQuery(SEARCH_BILLS, {
variables: { session: CURRENT_SESSION, limit: 200 },
});
const totalMPs = countsData?.mpsAggregate?.count || 338;
// Count only bills on order paper (current session, no royal assent)
const orderPaperBills =
orderPaperData?.searchBills?.filter((b: any) => {
if (!b.title) return false;
const status = (b.status || '').toLowerCase();
// Exclude bills that have received royal assent
return !status.includes('royal assent') && !status.includes('sanction royale');
})?.length || 0;
// TODO: Get actual new items count from API based on last visit
const newItemsCount = 12;
return (
<div className="min-h-screen flex flex-col bg-bg-primary">
<Header />
<main className="flex-1">
{/* Welcome Header */}
<div className="px-4 py-6 bg-gradient-to-r from-bg-elevated to-bg-secondary border-b border-border-subtle">
<div className="max-w-3xl mx-auto">
<div className="flex items-center justify-between">
<div>
<h1 className="text-2xl font-bold text-text-primary">
{firstName
? t('welcome.greeting', { name: firstName })
: t('welcome.greetingAnonymous')}
</h1>
<p className="text-sm text-text-secondary flex items-center gap-2 mt-1">
<span className="capitalize">{formattedDate}</span>
<span className="text-text-tertiary">•</span>
<span className="text-accent-red font-medium">
{t('welcome.newItems', { count: newItemsCount })}
</span>
</p>
</div>
<Link
href="/hansard"
className="flex items-center gap-2 px-4 py-2 rounded-full bg-bg-overlay hover:bg-bg-elevated border border-border-subtle transition-colors text-text-secondary hover:text-text-primary"
>
<Search size={16} />
<span className="text-sm hidden sm:inline">
{locale === 'fr' ? 'Rechercher' : 'Search Parliament'}
</span>
</Link>
</div>
</div>
</div>
{/* Active Discussions Carousel */}
<ActiveDiscussionsCarousel locale={locale} limit={9} autoScrollInterval={4000} />
{/* Compact Stat Pills - horizontal scroll */}
<div className="border-b border-border-subtle bg-bg-primary/50 backdrop-blur-sm">
<div className="max-w-3xl mx-auto">
<div className="flex gap-3 px-4 py-3 overflow-x-auto scrollbar-hide">
<StatPill
href="/mps"
value={totalMPs}
label={t('pills.mps')}
icon={Users}
/>
<StatPill
href="/bills"
value={orderPaperBills}
label={t('pills.activeBills')}
icon={FileText}
/>
<StatPill
href="/lobbying"
value="89"
label={t('pills.lobbying')}
icon={Building}
/>
<StatPill
href="/spending?year=2026"
value="$2.1M"
label={t('pills.spending')}
icon={DollarSign}
/>
</div>
</div>
</div>
{/* Activity Feed - The Hero */}
<div className="max-w-3xl mx-auto px-4 py-6">
{user ? (
<ActivityFeed locale={locale} limit={20} showFilters={true} />
) : (
<div className="text-center py-12">
<h2 className="text-xl font-semibold text-text-primary mb-2">
{locale === 'fr'
? 'Connectez-vous pour votre fil personnalisé'
: 'Sign in for your personalized feed'}
</h2>
<p className="text-text-secondary mb-4">
{locale === 'fr'
? "Suivez les députés, projets de loi et comités qui vous intéressent."
: 'Follow MPs, bills, and committees that matter to you.'}
</p>
<a
href="/auth/signin"
className="inline-flex items-center gap-2 px-6 py-3 rounded-lg bg-accent-red text-white font-medium hover:bg-accent-red-hover transition-colors"
>
{locale === 'fr' ? 'Se connecter' : 'Sign In'}
</a>
</div>
)}
</div>
</main>
<Footer />
</div>
);
}